"""
测试配置
定义测试固件和辅助函数
"""
import os
import tempfile
import pytest
from datetime import datetime
from app import create_app
from app.extensions import db
from app.models.user import User, UserRole
from app.models.product import Product, ProductVariant, ProductSpecification, ProductStatus
from app.models.order import Order, OrderItem, OrderStatus
from app.models.logistics import LogisticsProvider, Logistics, LogisticsStatus, TrackingNode
from app.models.inventory import InventoryRecord, InventoryType

@pytest.fixture
def app():
    """创建并配置一个Flask应用实例用于测试"""
    # 使用临时文件作为数据库文件
    db_fd, db_path = tempfile.mkstemp()
    
    app = create_app('testing')
    
    # 创建测试数据库并填充测试数据
    with app.app_context():
        db.create_all()
        # 创建测试用户
        admin = User(
            username='admin_test',
            email='admin@test.com',
            role=UserRole.ADMIN.value,
            full_name='测试管理员',
            is_active=True
        )
        admin.set_password('admin123')
        
        user = User(
            username='user_test',
            email='user@test.com',
            role=UserRole.USER.value,
            full_name='测试用户',
            is_active=True
        )
        user.set_password('user123')
        
        db.session.add_all([admin, user])
        db.session.commit()
    
    yield app
    
    # 清理
    os.close(db_fd)
    os.unlink(db_path)

@pytest.fixture
def client(app):
    """创建测试客户端"""
    return app.test_client()

@pytest.fixture
def runner(app):
    """创建命令行运行器"""
    return app.test_cli_runner()

@pytest.fixture
def admin_token(client):
    """获取管理员JWT令牌"""
    response = client.post('/api/auth/login', json={
        'username': 'admin_test',
        'password': 'admin123'
    })
    return response.json['access_token']

@pytest.fixture
def user_token(client):
    """获取普通用户JWT令牌"""
    response = client.post('/api/auth/login', json={
        'username': 'user_test',
        'password': 'user123'
    })
    return response.json['access_token']

@pytest.fixture
def admin_user(app):
    """创建管理员用户"""
    with app.app_context():
        user = User(
            username='admin',
            email='admin@example.com',
            role=UserRole.ADMIN.value,
            full_name='超级管理员'
        )
        user.set_password('Password123')
        db.session.add(user)
        db.session.commit()
        return user

@pytest.fixture
def normal_user(app):
    """创建普通用户"""
    with app.app_context():
        user = User(
            username='user',
            email='user@example.com',
            role=UserRole.USER.value,
            full_name='普通用户'
        )
        user.set_password('Password123')
        db.session.add(user)
        db.session.commit()
        return user

@pytest.fixture
def sample_product(app):
    """创建示例商品"""
    with app.app_context():
        product = Product(
            name='测试商品',
            description='这是一个测试商品',
            price=99.99,
            stock=100,
            sku='TEST-SKU-001',
            status=ProductStatus.ACTIVE.value
        )
        
        # 添加规格
        color_spec = ProductSpecification(
            name='颜色',
            product=product
        )
        color_spec.option_list = ['红色', '蓝色', '黑色']
        
        size_spec = ProductSpecification(
            name='尺寸',
            product=product
        )
        size_spec.option_list = ['S', 'M', 'L', 'XL']
        
        # 添加变体
        variant1 = ProductVariant(
            sku='TEST-SKU-001-1',
            price=99.99,
            stock=30,
            product=product
        )
        variant1.specifications = {'颜色': '红色', '尺寸': 'M'}
        
        variant2 = ProductVariant(
            sku='TEST-SKU-001-2',
            price=99.99,
            stock=40,
            product=product
        )
        variant2.specifications = {'颜色': '蓝色', '尺寸': 'L'}
        
        db.session.add(product)
        db.session.add(color_spec)
        db.session.add(size_spec)
        db.session.add(variant1)
        db.session.add(variant2)
        db.session.commit()
        
        return product

@pytest.fixture
def sample_order(app, normal_user, sample_product):
    """创建示例订单"""
    with app.app_context():
        order = Order(
            order_number=f"ORD-{datetime.now().strftime('%Y%m%d%H%M%S')}-{normal_user.id}",
            user_id=normal_user.id,
            status=OrderStatus.PENDING.value,
            total_amount=199.98,
            shipping_address='测试地址，测试城市，测试省份',
            shipping_method='标准快递',
            payment_method='在线支付'
        )
        
        # 添加订单项
        variant = sample_product.variants.first()
        
        order_item = OrderItem(
            order=order,
            product_id=sample_product.id,
            variant_id=variant.id if variant else None,
            quantity=2,
            price=99.99,
            subtotal=199.98
        )
        
        db.session.add(order)
        db.session.add(order_item)
        db.session.commit()
        
        return order

@pytest.fixture
def sample_logistics_provider(app):
    """创建示例物流服务商"""
    with app.app_context():
        provider = LogisticsProvider(
            name='测试物流',
            description='测试物流公司',
            website='http://example.com',
            contact='13800138000'
        )
        
        db.session.add(provider)
        db.session.commit()
        
        return provider

@pytest.fixture
def sample_logistics(app, sample_order, sample_logistics_provider):
    """创建示例物流单"""
    with app.app_context():
        logistics = Logistics(
            order_id=sample_order.id,
            provider_id=sample_logistics_provider.id,
            tracking_number='TEST123456789',
            status=LogisticsStatus.PROCESSING.value,
            shipping_address=sample_order.shipping_address
        )
        
        # 添加跟踪节点
        tracking_node = TrackingNode(
            logistics=logistics,
            status=LogisticsStatus.PROCESSING.value,
            location='物流中心',
            description='物流单已创建'
        )
        
        db.session.add(logistics)
        db.session.add(tracking_node)
        db.session.commit()
        
        return logistics 